package com.orange.delivery.presentation.page;

import java.io.Serializable;
import java.util.Locale;

import javax.servlet.http.HttpServletRequest;

import org.apache.wicket.AttributeModifier;
import org.apache.wicket.markup.html.WebPage;
import org.apache.wicket.markup.html.basic.Label;
import org.apache.wicket.markup.html.form.Button;
import org.apache.wicket.markup.html.form.Form;
import org.apache.wicket.markup.html.form.PasswordTextField;
import org.apache.wicket.markup.html.form.RequiredTextField;
import org.apache.wicket.markup.html.link.Link;
import org.apache.wicket.markup.html.panel.FeedbackPanel;
import org.apache.wicket.model.CompoundPropertyModel;
import org.apache.wicket.model.Model;
import org.apache.wicket.model.StringResourceModel;
import org.apache.wicket.request.mapper.parameter.PageParameters;
import org.slf4j.LoggerFactory;

import com.orange.delivery.presentation.WicketSession;

public class LoginPage extends WebPage {

	private static final long serialVersionUID = -9029748747538352173L;

	private static final transient org.slf4j.Logger LOG = LoggerFactory.getLogger(LoginPage.class);

	/**
	 * lang switch link
	 */
	private SwitchLangLink langLink;

	/**
	 * authentication feedback panel Is visible if authentication failed
	 */
	private FeedbackPanel authenticationFeedbackPanel;

	/**
	 * authentication form
	 */
	private Form<AuthenticationCredentials> authenticationForm;

	public LoginPage(PageParameters parameters) {
		super(parameters);
		initComponent();
	}

	private void initComponent() {
		createLoginPageTitle();
		createCurrentLocalSwitcher();
		createAuthenticationFeedback();
		createAuthenticationForm();
		createFooterInformation();
	}

	private void createLoginPageTitle() {
		Label loginPageTitle = new Label("loginPageTitle", getString("login.page.title"));
		add(loginPageTitle);
	}

	private void createFooterInformation() {
		// provide server informations, useful for session affinity tests
		HttpServletRequest servletReq = (HttpServletRequest) getRequest().getContainerRequest();
		LOG.debug("Local: {}:{} ", servletReq.getLocalName(), servletReq.getLocalPort());
		LOG.debug("Remote: {}:{} ", servletReq.getRemoteHost(), servletReq.getRemotePort());

		Label serverInfo = new Label("serverInfo", getString("login.page.server.value", new Model<Object[]>(new Object[] {
				servletReq.getServerName(), servletReq.getServerPort() })));
		serverInfo.add(new AttributeModifier("title", getString("login.page.server.title", new Model<Object[]>(new Object[] {
				servletReq.getLocalName(), servletReq.getLocalPort(), servletReq.getRemoteHost(), servletReq.getRemotePort() }))));
		add(serverInfo);

		// provide version informations, useful for continuous integration
		Label versionInfo = new Label("versionInfo", getString("login.page.version.value"));
		versionInfo.add(new AttributeModifier("title", getString("login.page.version.title")));
		add(versionInfo);
	}

	private void createAuthenticationForm() {

		authenticationForm = new Form<AuthenticationCredentials>("gassiAuthenticationForm",
				new CompoundPropertyModel<AuthenticationCredentials>(new AuthenticationCredentials())) {
			private static final long serialVersionUID = 1L;

			@Override
			protected void onSubmit() {
				AuthenticationCredentials creds = (AuthenticationCredentials) getDefaultModelObject();
				signIn(creds);
			}

			private void signIn(AuthenticationCredentials creds) {
				boolean successful = WicketSession.get().signIn(creds.getUsername(), creds.getPassword());
				if (successful) {
					continueToOriginalDestination();
					setResponsePage(HomePage.class);
				} else {
					authenticationFeedbackPanel.error("Login failed. Bad username or password. Please try again");
				}
			}
		};

		add(authenticationForm);

		RequiredTextField<String> usernameTextField = new RequiredTextField<String>("username");
		authenticationForm.add(usernameTextField);

		PasswordTextField passwordTextField = new PasswordTextField("password");
		passwordTextField.setRequired(true);
		authenticationForm.add(passwordTextField);

		Button authenticationSubmit = new Button("authenticationSubmit");
		authenticationForm.add(authenticationSubmit);
	}

	private void createAuthenticationFeedback() {

		authenticationFeedbackPanel = new FeedbackPanel("authenticationFeedback");
		add(authenticationFeedbackPanel);
	}

	private void createCurrentLocalSwitcher() {

		Locale currentLocale = getSession().getLocale();
		String localeDisplayName = currentLocale.getDisplayName();
		LOG.debug("refreshSwitchLangLink() : current local display name : {} ", localeDisplayName);
		if (Locale.FRENCH.equals(currentLocale)) {
			langLink = new SwitchLangLink("switchLangLink", Locale.ENGLISH);
		} else {
			langLink = new SwitchLangLink("switchLangLink", Locale.FRENCH);
		}

		add(langLink);

		langLink.add(new Label("lang", getStringResourceModel("login.page.lang.switch")));
	}

	/**
	 * Define link for switching locale
	 */
	private class SwitchLangLink extends Link<Void> {

		private static final long serialVersionUID = -4849232308019888045L;
		private Locale locale;

		public SwitchLangLink(String id, Locale locale) {
			super(id);
			this.locale = locale;
		}

		@Override
		public void onClick() {
			LOG.debug("Lang switch to " + locale.toString());
			getSession().setLocale(locale);
			if (Locale.FRENCH.equals(locale)) {
				this.locale = Locale.ENGLISH;
			} else {
				this.locale = Locale.FRENCH;
			}
			setResponsePage(this.getPage());
		}
	}

	private StringResourceModel getStringResourceModel(java.lang.String key) {
		// fix Localizer warning : cf.
		// https://issues.apache.org/jira/browse/WICKET-990
		return new StringResourceModel(key, this, null);
	}
}

class AuthenticationCredentials implements Serializable {

	private static final long serialVersionUID = 1L;
	private String username;
	private String password;

	public String getUsername() {
		return username;
	}

	public void setUsername(String username) {
		this.username = username;
	}

	public String getPassword() {
		return password;
	}

	public void setPassword(String password) {
		this.password = password;
	}
}
